<template>
  <div id="detail">
    <!-- nav-bar导航 -->
    <detail-nav-bar ref="navbar" class="detail-nav-bar" @navClick="navClick"></detail-nav-bar>

    <!-- better-scroll组件引入 -->
    <scroll ref="scroll" class="detail-content-view" :probe-type="3" @scroll="detailScroll">
      <!-- 轮播图 -->
      <detail-swiper :topImages="topImages"></detail-swiper>

      <!-- 商品基本信息 -->
      <detail-base-info :goods="goods"></detail-base-info>

      <!-- 店铺信息 -->
      <detail-shop-info :shops="shops"></detail-shop-info>

      <!-- 商品详情信息 -->
      <detail-goods-info :detail-info="detailInfo" @imageLoad="imageLoad"></detail-goods-info>

      <!-- 商品参数信息 -->
      <detail-params-info ref="params" :params-info="paramsInfo"></detail-params-info>

      <!-- 商品评论信息 -->
      <detail-comment-info ref="comment" :comment-info="commentInfo"></detail-comment-info>

      <!-- 推荐数据信息 -->
      <goods-list ref="recommend" :goods="recommends"></goods-list>
    </scroll>

    <detail-bottom-bar @addToCart="addToCart"></detail-bottom-bar>
    <!-- 返回顶部小icon 自定义组件监听点击需要加上.native修饰符 -->
    <back-top @click.native="backTop" v-show="isShowBack"></back-top>

    <!-- 吐司 -->
    <!-- <toast :message="toastMessage" :is-show="toastisShow"></toast> -->
  </div>
</template>

<script>
// 引入公共组件
import Scroll from "components/common/scroll/Scroll";
import GoodsList from "components/content/goods/GoodsList";
// import Toast from "components/common/toast/Toast";
// ps: 已在混入对象中导入
// import BackTop from "components/content/backTop/BackTop";

// 引入子组件
import DetailNavBar from "./childComps/DetailNavBar";
import DetailSwiper from "./childComps/DetailSwiper";
import DetailBaseInfo from "./childComps/DetailBaseInfo";
import DetailShopInfo from "./childComps/DetailShopInfo";
import DetailGoodsInfo from "./childComps/DetailGoodsInfo";
import DetailParamsInfo from "./childComps/DetailParamsInfo";
import DetailCommentInfo from "./childComps/DetailCommentInfo";
import DetailBottomBar from "./childComps/DetailBottomBar";

// 引入后端API/封装类
import { getDetail, getRecommend, Goods, Shops, GoodParams } from "@/api";

// 引入工具类
import { debounce } from "utils/utils";
// import { BACK_POSITION } from "utils/const";
import { mapActions } from "vuex";

// 引入混入对象
import { MrchenMixin, backTopMixin } from "utils/mixin";

export default {
  name: "Detail",

  // 组件注册
  components: {
    Scroll,
    // ps: 已在混入对象中注册
    // BackTop,
    GoodsList,
    // ps: 组件调用过程太过繁琐, 进阶封装 >>> [插件式封装]
    // Toast,
    DetailNavBar,
    DetailSwiper,
    DetailBaseInfo,
    DetailShopInfo,
    DetailGoodsInfo,
    DetailParamsInfo,
    DetailCommentInfo,
    DetailBottomBar,
  },

  mixins: [MrchenMixin, backTopMixin],

  // 组件变量
  data() {
    return {
      // 当前详情页数据iid
      iid: "",
      // 顶部轮播图数据
      topImages: [],
      // 详情页基本信息对象
      goods: {},
      // 店铺信息对象
      shops: {},
      // 商品详情信息对象
      detailInfo: {},
      // 商品参数信息对象
      paramsInfo: {},
      // 商品评论信息对象
      commentInfo: {},
      // 详情页推荐信息列表
      recommends: [],
      // 滚动位置列表 >>> [y轴]
      themeTopYs: [],
      // 记录nav-bar的下标 用于减少判断
      navBarIndex: 0,
      // 是否显示回到顶部按钮 ps: 已在混入对象中定义
      // isShowBack: false,
      // 吐司消息文字
      toastMessage: "",
      // 吐司是否显示
      toastisShow: false,
    };
  },

  // 回调 >>> 组件被创建时
  created() {
    this.iid = this.$route.query.iid;
    // 根据iid请求数据
    this.getData();

    // 测试混入对象中的方法是否可以使用
    // this.runBoy();
  },

  // 回调 >>> 组件被挂载后
  mounted() {
    // 创建一个防抖函数
    const refresh = debounce(this.$refs.scroll.refresh, 100);

    // 1. 监听GoodsItem中图片加载完成 >>> [事件总线]
    this.$bus.$on("detailItemImgLoad", () => {
      // 调用防抖函数
      refresh();
    });
  },

  // 回调 >>> 组件更新变化就触发
  // updated() {
  //   console.log("[updated] 组件更新中");
  //   // 2. 获取各个标题的offsetTop高度
  //   // 商品
  //   this.themeTopYs.push(0);
  //   // 参数
  //   this.themeTopYs.push(this.$refs.params.$el.offsetTop);
  //   // 评论
  //   this.themeTopYs.push(this.$refs.comment.$el.offsetTop);
  //   // 推荐
  //   this.themeTopYs.push(this.$refs.recommend.$el.offsetTop);
  //   console.log("[滚动高度列表] >>>", this.themeTopYs);
  // },

  // 组件方法
  methods: {
    // =============================================== 后端API ===============================================
    getData() {
      // 获取详情所需数据
      getDetail({ iid: this.iid }).then((res) => {
        // console.log("[正常] 详情页数据 >>>", res);
        const data = res.result;

        // 1. 获取顶部轮播图信息
        this.topImages = data.itemInfo.topImages;
        // 2. 获取商品基本信息
        this.goods = new Goods(
          data.itemInfo,
          data.columns,
          data.shopInfo.services
        );
        // 3. 获取店铺信息
        this.shops = new Shops(data.shopInfo);
        // 4. 获取商品详细信息
        this.detailInfo = data.detailInfo;
        // 5. 获取商品参数信息
        this.paramsInfo = new GoodParams(
          data.itemParams.info,
          data.itemParams.rule
        );
        // 6. 获取评论信息 ps: 先判断有没有
        this.commentInfo = data.rate.cRate ? data.rate.list[0] : {};

        // 7. 获取各个标题的offsetTop高度
        // this.$nextTick(() => {});
      });

      // 获取推荐所需数据
      getRecommend().then((res) => {
        // console.log("[正常] 详情页推荐数据 >>>", res);
        this.recommends = res.data.list;
      });
    },

    // =============================================== 功能函数 ===============================================
    ...mapActions(["addCart"]),

    //=============================================== 事件监听 ===============================================
    // 图片监听回调
    imageLoad() {
      // 1. 重新计算可滚动区域高度
      this.$refs.scroll.refresh();

      // 2. 获取各个标题的offsetTop高度
      // 根据最新的数据, 对应的DOM是已经被渲染出来, 但是图片依然是么有加载完(目前获取到的offsetTop不包含图片)
      // offsetTop值不正确的时候, 基本都是因为图片的问题
      this.themeTopYs = [];
      // 商品
      this.themeTopYs.push(0);
      // 参数
      this.themeTopYs.push(this.$refs.params.$el.offsetTop);
      // 评论
      this.themeTopYs.push(this.$refs.comment.$el.offsetTop);
      // 推荐
      this.themeTopYs.push(this.$refs.recommend.$el.offsetTop);
      console.log("[滚动高度列表] >>>", this.themeTopYs);
    },

    // nav-bar导航点击
    navClick(index) {
      let scrollY = -this.themeTopYs[index];
      // 除了最顶部的 其余标题滚动需要加上顶部44像素
      if (index != 0) scrollY += 44;
      // 滚动到相应标题所在区域
      this.$refs.scroll.scrollTo(0, scrollY, 400);
    },

    // 详情页滚动事件监听
    detailScroll(position) {
      // console.log(position);
      // 1. 取出监听滚动时的y值
      const positionY = -position.y + 44;
      const len = this.themeTopYs.length - 1;

      // 2. 将y值与当前滚动列表中存储的y值做比较
      // 例如滚动列表中存储为 [0, 7000, 9000, 12000]
      // Y在 0-7000 之间或等于时, index = 0,
      // Y在 7000-9000 之间或等于时, index = 1,
      // Y在 9000-12000 之间或等于时, index = 2,
      // Y超过 12000 时, index = 3
      this.themeTopYs.forEach((item, index, list) => {
        // index在使用for in 遍历时, 类型为字符串需要转换成数字parseInt(str), 所以我用forEach...
        // 如何获取一个正确的值呢? 设置一个区间获取一个可控的滚动值
        if (
          this.navBarIndex != index &&
          ((index < len && positionY >= item && positionY < list[index + 1]) ||
            (index == len && positionY >= item))
        ) {
          this.$refs.navbar.currentIndex = this.navBarIndex = index;
          console.log("当前滚动Y轴值为 >>>", positionY, index, item);
        }
      });

      this.listenShowBack(position.y);
    },

    // 添加购物车
    addToCart() {
      console.log("[详情页] 购物车商品添加中...");
      // 1. 获取购物车需要展示的信息
      const product = {
        // iid: 唯一标识
        iid: this.iid,
        // 图片
        image: this.topImages[0],
        // 标题
        title: this.goods.title,
        // 描述
        desc: this.goods.desc,
        // 价格
        price: this.goods.realPrice,
      };

      // 2. 将商品提交到vuex中
      // 改变主意了 先给actions
      // this.$store.dispatch("addCart", product).then((res) => {
      //   console.log(res);
      // });
      this.addCart(product).then((res) => {
        // this.toastMessage = res;
        // this.toastisShow = true;
        // setTimeout(() => {
        //   this.toastisShow = false;
        //   this.toastMessage = "";
        // }, 1800);

        // 使用进阶封装的toast
        console.log(this.$toast);
        this.$toast.show(res);
      });
    },
  },
};
</script>

<style lang="less" scoped>
#detail {
  position: relative;
  height: 100vh;
  // background-color: var(--color-background);
  z-index: 1;
  .detail-nav-bar {
    // 详情导航条
    // position: relative;
    // z-index: 9;
    background-color: var(--color-background);
  }
  .detail-content-view {
    // 详情内容
    height: calc(100% - 44px - 58px);
    overflow: hidden;
  }
}
</style>